Skip to content

Store the document PDF on quorum request - #1794

Open
SachaProbo wants to merge 1 commit into
mainfrom
SachaProbo/quorum-request-pdf
Open

Store the document PDF on quorum request#1794
SachaProbo wants to merge 1 commit into
mainfrom
SachaProbo/quorum-request-pdf

Conversation

@SachaProbo

@SachaProbo SachaProbo commented Aug 28, 2026

Copy link
Copy Markdown
Contributor

A refused quorum previously had no file of its own, so the reviewed version was lost after a later quorum was accepted.

Generate the PDF in a dedicated worker so Chrome does not hold database locks, and keep the file internal to the quorum row.


Summary by cubic

A refused quorum previously had no file of its own, so the reviewed version was lost after a later quorum was accepted. This PR stores the reviewed document as a PDF on the quorum row, generated by a dedicated worker so Chrome never holds database locks, and exposes the quorum through the GraphQL Node interface.

Coredata +289 -13

  • Adds file_id, pdf_attempt_count, and pdf_claimed_at to quorums via a new migration.
  • ClaimNextWithoutFileForUpdate atomically claims the oldest pending quorum without a PDF, skipping locked rows and expired claims, and increments the attempt counter.
  • HasPDFClaim, AttachPDFFile, and ReleasePDFClaim guard the claim lifecycle so the file attaches only while the claim is held and failures retry.

Service +341 -11

  • Adds a polling worker that claims quorums without a PDF, renders the document version, and uploads it as a private file.
  • Releases the claim on failure so attempts retry, and attaches the file only while the claim is still held and the quorum has none.
  • Splits PDF generation into loadDocumentPDFInput and renderDocumentPDF for reuse, and wires the worker into probod startup and shutdown.

GraphQL API +10 -0

  • Resolves quorum IDs through the Node interface using the existing ActionDocumentVersionApprovalList permission.

Written for commit 4c0bc92. Summary will update on new commits.

Review in cubic

@SachaProbo
SachaProbo force-pushed the SachaProbo/quorum-request-pdf branch 2 times, most recently from 709f7ac to beae13d Compare August 28, 2026 12:31

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All reported issues were addressed

Reply with feedback, questions, or to request a fix.

Fix all with cubic | Re-trigger cubic

Comment thread pkg/probo/document_approval_quorum_pdf_worker.go
Comment thread pkg/probo/document_approval_quorum_pdf_worker.go Outdated
Comment thread pkg/coredata/document_version_approval_quorum.go
@SachaProbo
SachaProbo force-pushed the SachaProbo/quorum-request-pdf branch from beae13d to 77e6d8e Compare August 28, 2026 12:39

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All reported issues were addressed across 6 files (changes from recent commits).

Requires human review: Auto-approval blocked because this review re-detected 2 unresolved issues already reported by Cubic.
Tip: instead of fixing issues one by one fix them all with cubic
Tip: Review your code locally with the cubic CLI to iterate faster.

Re-trigger cubic

Comment thread pkg/probo/document_approval_quorum_pdf_worker.go Outdated
Comment thread pkg/probo/document_approval_service.go Outdated
Comment thread pkg/coredata/migrations/20260828T112305Z.sql
Comment thread pkg/coredata/document_version_approval_quorum.go Outdated
Comment thread pkg/probo/document_approval_service.go Outdated
@SachaProbo
SachaProbo force-pushed the SachaProbo/quorum-request-pdf branch 2 times, most recently from 1e284c0 to 0392e95 Compare August 28, 2026 13:06

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All reported issues were addressed across 8 files (changes from recent commits).

Tip: instead of fixing issues one by one fix them all with cubic
Tip: Review your code locally with the cubic CLI to iterate faster.

Re-trigger cubic

Comment thread pkg/probo/document_approval_service.go
Comment thread pkg/probo/document_approval_quorum_pdf_worker.go Outdated
Comment thread pkg/probo/document_approval_service.go
Comment thread pkg/coredata/migrations/20260828T112305Z.sql
Comment thread pkg/probo/document_approval_quorum_pdf_worker.go Outdated
Comment thread pkg/probod/probod.go
Comment thread pkg/probod/probod.go Outdated
@SachaProbo
SachaProbo force-pushed the SachaProbo/quorum-request-pdf branch 2 times, most recently from d919f37 to c412cb0 Compare August 28, 2026 13:19

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All reported issues were addressed across 7 files (changes from recent commits).

Tip: Review your code locally with the cubic CLI to iterate faster.

Fix all with cubic | Re-trigger cubic

Comment thread pkg/probo/document_approval_service.go
@SachaProbo
SachaProbo force-pushed the SachaProbo/quorum-request-pdf branch from c412cb0 to dda2602 Compare August 28, 2026 13:34

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All reported issues were addressed across 7 files (changes from recent commits).

Requires human review: Auto-approval blocked because this review re-detected 1 unresolved issue already reported by Cubic.
Tip: Review your code locally with the cubic CLI to iterate faster.

Fix all with cubic | Re-trigger cubic

Comment thread pkg/coredata/document_version_approval_quorum.go
Comment thread pkg/probo/document_approval_quorum_pdf_worker.go
Comment thread pkg/coredata/document_version_approval_quorum.go
@SachaProbo
SachaProbo requested a review from a team August 28, 2026 14:15
A refused quorum previously had no file of its own, so the
reviewed version was lost after a later quorum was accepted.

Generate the PDF in a dedicated worker so Chrome does not
hold database locks, and keep the file internal to the
quorum row.

Signed-off-by: Sacha Al Himdani <sacha@probo.com>
@SachaProbo
SachaProbo force-pushed the SachaProbo/quorum-request-pdf branch from dda2602 to 4c0bc92 Compare September 1, 2026 11:26

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

3 issues found across 7 files (changes from recent commits).

Heads up: you’re close to your included review allowance. Set a flex budget so reviews don’t pause.

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="pkg/probo/document_approval_service.go">

<violation number="1" location="pkg/probo/document_approval_service.go:1113">
P2: When the attach transaction fails or the PDF claim expires during generation, this upload leaves an unreferenced private object because the subsequent transaction rolls back and the worker retries. Delete the uploaded object on every post-upload failure, including the lost-claim path, or use a cleanup mechanism for these orphaned uploads.</violation>
</file>

<file name="pkg/probo/document_approval_quorum_pdf_worker.go">

<violation number="1" location="pkg/probo/document_approval_quorum_pdf_worker.go:65">
P1: When a quorum is rejected before this worker claims it, the worker can never process it because `ClaimNextWithoutFileForUpdate` only selects `PENDING` rows. Queue the PDF at quorum creation or allow the claim to cover the terminal quorum state so rapid refusals still retain their reviewed version.</violation>
</file>

<file name="pkg/coredata/document_version_approval_quorum.go">

<violation number="1" location="pkg/coredata/document_version_approval_quorum.go:490">
P1: When a quorum is rejected, approved, or voided before PDF processing completes, these `PENDING` checks make the worker abandon the claim, so the quorum remains fileless. Select unfiled quorums regardless of final status and validate and attach using the claim timestamp and `file_id IS NULL`.</violation>
</file>

Tip: Review your code locally with the cubic CLI to iterate faster.

Fix all with cubic | Re-trigger cubic

if err := h.service.pg.WithTx(
ctx,
func(ctx context.Context, tx pg.Tx) error {
return quorum.ClaimNextWithoutFileForUpdate(

@cubic-dev-ai cubic-dev-ai Bot Sep 1, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1: When a quorum is rejected before this worker claims it, the worker can never process it because ClaimNextWithoutFileForUpdate only selects PENDING rows. Queue the PDF at quorum creation or allow the claim to cover the terminal quorum state so rapid refusals still retain their reviewed version.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At pkg/probo/document_approval_quorum_pdf_worker.go, line 65:

<comment>When a quorum is rejected before this worker claims it, the worker can never process it because `ClaimNextWithoutFileForUpdate` only selects `PENDING` rows. Queue the PDF at quorum creation or allow the claim to cover the terminal quorum state so rapid refusals still retain their reviewed version.</comment>

<file context>
@@ -0,0 +1,122 @@
+	if err := h.service.pg.WithTx(
+		ctx,
+		func(ctx context.Context, tx pg.Tx) error {
+			return quorum.ClaimNextWithoutFileForUpdate(
+				ctx,
+				tx,
</file context>
Fix with cubic

WHERE
q.file_id IS NULL
AND q.pdf_attempt_count < @max_pdf_attempts
AND q.status = @status

@cubic-dev-ai cubic-dev-ai Bot Sep 1, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1: When a quorum is rejected, approved, or voided before PDF processing completes, these PENDING checks make the worker abandon the claim, so the quorum remains fileless. Select unfiled quorums regardless of final status and validate and attach using the claim timestamp and file_id IS NULL.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At pkg/coredata/document_version_approval_quorum.go, line 490:

<comment>When a quorum is rejected, approved, or voided before PDF processing completes, these `PENDING` checks make the worker abandon the claim, so the quorum remains fileless. Select unfiled quorums regardless of final status and validate and attach using the claim timestamp and `file_id IS NULL`.</comment>

<file context>
@@ -435,3 +459,228 @@ WHERE
+WHERE
+	q.file_id IS NULL
+	AND q.pdf_attempt_count < @max_pdf_attempts
+	AND q.status = @status
+	AND d.deleted_at IS NULL
+	AND (
</file context>
Fix with cubic

UpdatedAt: now,
}

fileSize, err := s.svc.fileManager.PutFile(

@cubic-dev-ai cubic-dev-ai Bot Sep 1, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: When the attach transaction fails or the PDF claim expires during generation, this upload leaves an unreferenced private object because the subsequent transaction rolls back and the worker retries. Delete the uploaded object on every post-upload failure, including the lost-claim path, or use a cleanup mechanism for these orphaned uploads.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At pkg/probo/document_approval_service.go, line 1113:

<comment>When the attach transaction fails or the PDF claim expires during generation, this upload leaves an unreferenced private object because the subsequent transaction rolls back and the worker retries. Delete the uploaded object on every post-upload failure, including the lost-claim path, or use a cleanup mechanism for these orphaned uploads.</comment>

<file context>
@@ -1011,6 +1013,148 @@ func (s *DocumentApprovalService) generateApprovalPDF(
+		UpdatedAt:      now,
+	}
+
+	fileSize, err := s.svc.fileManager.PutFile(
+		ctx,
+		fileRecord,
</file context>
Fix with cubic

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant